package drds.plus.rule_engine.table_rule;

import drds.plus.rule_engine.rule.Rule;
import drds.plus.rule_engine.rule.RuleColumn;
import drds.plus.rule_engine.rule.WrappedGroovyRule;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.util.*;

/**
 * 类名取名兼容老的rule代码<br/>
 * 描述一个逻辑表怎样分库分表，允许指定逻辑表名和db/table的{@linkplain Rule}规则
 *
 * <pre>
 *   一个配置事例：
 *   -----------
 *   <!-- 按照user_id取模划分64张表,表明具体为'user_0000'-'user_0063'，
 *   'user_0000'-'user_0031' 在'TDDL_0000_GROUP'中，
 *   'user_0032'-'user_0063' 在'TDDL_0001_GROUP'中 -->
 *   <rule id="user_bean" class="com.taobao.tddl.rule_engine.VirtualTable">
 *
 *     <!-- 具体表名格式框架，{}中的数将会被tbRuleArray的值替代，并保持位数 -->
 *     <property id="tableNamePattern" value="user_{0000}"></property>
 *
 *     <!-- 全表扫描开关，默认关闭，是否允许应用端在没有给定分表键值的情况下查询全表 -->
 *     <property id="allowFullTableScan" value="true"/>
 *   </rule>
 * </pre>
 */
@Slf4j
public class TableRule extends AbstractITableRule implements ITableRule {

    @Setter
    @Getter
    protected String tableNamePattern; // item_{0000}

    @Setter
    @Getter
    protected String[] tbRules; // rule配置字符串


    @Setter
    @Getter
    protected boolean allowFullTableScan = false; // 是否允许全表扫描
    @Setter
    @Getter
    protected boolean disableFullTableScan = true; // 是否关闭全表扫描

    @Setter
    @Getter
    protected String tableSlotKeyFormat;

    @Setter
    @Getter
    protected Rule rule;
    @Setter
    @Getter
    protected List<String> shardColumnNameList; // 分库字段
    @Setter
    @Getter
    protected Object outerContext;

    /**
     * 是否是个广播表，optimizer模块需要用他来标记某个表是否需要进行复制
     */
    @Setter
    @Getter
    protected boolean broadcast = false;

    /**
     * 相同的join data node 应该具有相同的切分规则
     */
    @Setter
    @Getter
    protected String joinDataNodeId = null;

    public void doInit() {


        rule = new WrappedGroovyRule(null, null, null);

        // 构造一下分区字段
        buildShardColumns();


    }


    private void buildShardColumns() {
        Set<String> shardColumns = new HashSet<String>();
        Map<String, RuleColumn> columRule = rule.getColumnNameToRuleColumnMap();
        if (null != columRule && !columRule.isEmpty()) {
            shardColumns.addAll(columRule.keySet());
        }
        this.shardColumnNameList = new ArrayList<String>(shardColumns);// 没有表配置，代表没有走分区
    }

    public Logger log() {
        return log;
    }
}
